package com.jxtc.enterprise.hr.controller;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.jxtc.enterprise.common.utils.Result;
import com.jxtc.enterprise.common.utils.ResultGenerator;
import com.jxtc.enterprise.common.vo.PaginationResponseVO;
import com.jxtc.enterprise.hr.dto.*;
import com.jxtc.enterprise.hr.service.HrEmployeeManagementService;
import com.jxtc.enterprise.hr.vo.EmployeeVO;
import com.jxtc.enterprise.hr.vo.req.EmployeeBindCompanyReqVo;
import com.jxtc.enterprise.hr.vo.req.UserOtherCompRelationCreateRespVo;
import com.jxtc.enterprise.hr.vo.resp.CompanyWithDepartmentInfoRespVo;
import com.jxtc.enterprise.hr.vo.resp.OtherCanOrderFoodCompanyCascadeRespVo;
import com.jxtc.enterprise.hr.vo.resp.UserOtherCompanyRelationRespVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/jxtc/enterprise/employee")
@RequiredArgsConstructor
@Slf4j
public class EmployeeManagementController {

    private final HrEmployeeManagementService hrEmployeeManagementService;

    @ApiResponse(responseCode = "200", description = "code 为 200 时，data 字段为员工信息列表")
    @Parameter(name = "size", description = "每页显示的记录数，默认为 10")
    @Parameter(name = "page", description = "当前页码，从 1（默认值）开始")
    @Parameter(name = "name", description = "查询的员工姓名，如果为空则查询全部员工信息")
    @Parameter(name = "companyId", description = "查询的员工所在公司 ID，必传项", example = "c752804d0cd410267f404dd3f0457a57")
    @Operation(summary = "6.1 根据员工姓名查询员工信息列表", description = "员工名称可以不传，不传时默认查询所有员工信息", tags = {"6. 员工管理"}, operationId = "6.1")
    @GetMapping("/list")
    public Result<PaginationResponseVO<EmployeeVO>> listByName(String companyId,
                                                               @RequestParam(required = false) String name,
                                                               @RequestParam(required = false, defaultValue = "1") int page,
                                                               @RequestParam(required = false, defaultValue = "10") int size) {
        PaginationResponseVO<EmployeeVO> vo = hrEmployeeManagementService.pageByName(companyId, name, page, size);
        return ResultGenerator.genSuccessResult(vo);
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示新增员工成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示新增员工失败，此时 message 字段给出错误信息")
    @Operation(summary = "6.2 新增员工", tags = {"6. 员工管理"}, operationId = "6.2")
    @PostMapping
    public Result<Void> addEmployee(@Valid @RequestBody EmployeeDTO dto) {
        hrEmployeeManagementService.saveEmployee(dto);
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示编辑员工成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示编辑员工失败，此时 message 字段给出错误信息")
    @Operation(summary = "6.3 编辑员工", tags = {"6. 员工管理"}, operationId = "6.3")
    @PutMapping
    public Result<Void> editEmployee(@Valid @RequestBody EmployeeUpdateDTO dto) {
        hrEmployeeManagementService.updateEmployee(dto);
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示为指定员工充值成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示为指定员工充值失败，此时 message 字段给出错误信息")
    @Operation(summary = "6.4 根据员工 ID 对指定员工进行充值", description = "如果员工 ID 列表中数据超过 1 个，则为批量充值", tags = {"6. 员工管理"}, operationId = "6.4")
    @PutMapping("/recharge")
    public Result<Void> recharge(@Valid @RequestBody RechargeDTO dto) {
        log.info("recharge dto: {}", dto);
        hrEmployeeManagementService.rechargeEmployee(dto);
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示批量为员工充值成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示批量为员工充值失败，此时 message 字段给出错误信息")
    @Operation(summary = "6.5 根据公司 ID 对员工进行批量充值", tags = {"6. 员工管理"}, operationId = "6.5")
    @PutMapping("/batch/recharge")
    public Result<Void> batchRechargeByCompanyId(@Valid @RequestBody BatchRechargeDTO dto) {
        log.info("batch recharge dto: {}", dto);
        hrEmployeeManagementService.rechargeEmployeeByCompanyId(dto);
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示导入员工信息成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示导入员工信息失败，此时 message 字段给出错误信息")
    @Parameter(name = "companyId", description = "公司 ID", example = "c752804d0cd410267f404dd3f0457a57")
    @Operation(summary = "6.6 通过上传 Excel 文件批量导入员工信息", tags = {"6. 员工管理"}, operationId = "6.6")
    @PostMapping(value = "/excel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result<Void> uploadExcel(String companyId,
                                    @Parameter(description = "符合 excel 模板的员工信息文件") @RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return ResultGenerator.genFailResult("文件内容为空，请重新上传");
        }

        try (ExcelReader reader = ExcelUtil.getReader(file.getInputStream())) {
            List<List<Object>> readAll = reader.read();
            for (List<Object> rowData : readAll) {
                log.info("{}", rowData);
            }
            // 跳过第一行数据（标题栏）
            List<List<Object>> rows = readAll.stream().skip(1).collect(Collectors.toList());
            hrEmployeeManagementService.saveEmployeeByExcel(companyId, rows);
        } catch (Exception e) {
            log.error("解析 Excel 文件失败", e);
            return ResultGenerator.genFailResult("解析 Excel 文件失败");
        }
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "文件下载成功")
    @Operation(summary = "6.7 下载员工导入模板", tags = {"6. 员工管理"}, operationId = "6.7")
    @GetMapping("/excel/template")
    public void downloadExcelTemplate(HttpServletResponse response) {

        try (ExcelWriter writer = ExcelUtil.getWriter(true)) {
            // 设置样式
            CellStyle style = writer.getCellStyle();
            // 设置垂直居中和水平居中
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setAlignment(HorizontalAlignment.CENTER);
            // 对所有列设置宽度
            writer.setColumnWidth(-1, 24);

            Map<String, Object> row = new LinkedHashMap<>();
            row.put("姓名", "张三");
            row.put("部门", "技术部");
            row.put("手机号", "13812345678");

            // 添加一行作为示例数据
            writer.write(Collections.singleton(row), true);

            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=template.xlsx");
            writer.flush(response.getOutputStream(), true);
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw new RuntimeException("Error while generating Excel file", e);
        }
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示软删除员工成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示软删除员工失败，此时 message 字段给出错误信息")
    @Parameter(name = "id", description = "员工 ID", example = "c752804d0cd410267f404dd3f0457a57")
    @Operation(summary = "6.8 软删除员工信息", tags = {"6. 员工管理"}, operationId = "6.8")
    @DeleteMapping
    public Result<Void> deleteEmployeeById(String id) {
        hrEmployeeManagementService.deleteEmployeeById(id);
        return ResultGenerator.genSuccessResult();
    }

    @ApiResponse(responseCode = "200", description = "code 为 200 时， 表示清空员工余额成功，此时 data 字段为空")
    @ApiResponse(responseCode = "200", description = "code 为 400 时， 表示清空员工余额失败，此时 message 字段给出错误信息")
    @Operation(summary = "6.9 清空员工余额", tags = {"6. 员工管理"}, operationId = "6.9")
    @PutMapping("/clearEmployeeBalanceById")
    public Result<Void> clearEmployeeBalanceById(@Valid @RequestBody ClearBalanceDTO dto) {
        hrEmployeeManagementService.clearEmployeeBalanceById(dto.getEmployeeId());
        return ResultGenerator.genSuccessResult();
    }

    @Operation(summary = "6.10 批量编辑员工每餐限购份数", tags = {"6. 员工管理"}, operationId = "6.10")
    @PostMapping("/batchEditEmployeeFoodLimitCount")
    public Result<Void> batchEditEmployeeFoodLimitCount(@RequestBody BatchEditEmployeeFoodCountLimitDTO dto) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /batchEditEmployeeFoodLimitCount, companyId: {}, employee ids: {}", requestId, dto.getCompanyId(), dto.getEmployeeIds());
        int updateCount = hrEmployeeManagementService.batchEditEmployeeFoodLimitCount(dto.getCompanyId(), dto.getEmployeeIds(), dto.getLimitCount());
        log.info("requestId {}, hr view, /batchEditEmployeeFoodLimitCount, records update: {}", requestId, updateCount);
        return ResultGenerator.genSuccessResult();
    }

    @Operation(summary = "6.11 导出公司所有员工信息到excel表格", tags = {"6. 员工管理"}, operationId = "6.11")
    @GetMapping("/exportAllEmployeeInfoToExcel")
    public void exportAllEmployeeInfoToExcel(@RequestParam("companyId") String companyId, HttpServletResponse response) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /exportAllEmployeeInfoToExcel, companyId: {}", requestId, companyId);
        hrEmployeeManagementService.exportAllEmployeeInfo2Excel(companyId, response);
        log.info("requestId {}, hr view, /exportAllEmployeeInfoToExcel, successfully", requestId);
    }


    /**
     * 3.1.12 通过员工 ID 查询该员工已绑定的其它可点餐的公司及部门信息列表
     *
     * @param employeeId 员工 ID
     */
    @GetMapping("/queryCompanyAndDepartmentListByEmployeeId")
    public Result<List<UserOtherCompanyRelationRespVo>> queryCompanyAndDepartmentListByEmployeeId(@RequestParam(value = "employeeId") String employeeId) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /queryCompanyAndDepartmentListByEmployeeId, employeeId: {}", requestId, employeeId);
        List<UserOtherCompanyRelationRespVo> voList = hrEmployeeManagementService.queryCompanyAndDepartmentListByEmployeeId(employeeId);
        log.info("requestId {}, hr view, /queryCompanyAndDepartmentListByEmployeeId, response: {}", requestId, JSONObject.toJSONString(voList));
        return ResultGenerator.genSuccessResult(voList);
    }


    /**
     * 3.1.13 通过公司 ID 和员工 ID 查询该员工尚未绑定的其它可点餐的公司及部门信息列表
     *
     * @param companyId  公司 ID
     * @param employeeId 员工 ID，用于排除当前员工已绑定的可点餐公司列表
     */
    @GetMapping("/queryOtherCompanyAndDepartmentByCompanyIdAndEmployeeId")
    public Result<List<CompanyWithDepartmentInfoRespVo>> queryOtherCompanyAndDepartmentByCompanyIdAndEmployeeId(@RequestParam(value = "companyId") String companyId,
                                                                                                                @RequestParam(value = "employeeId") String employeeId) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /queryOtherCompanyAndDepartmentByCompanyIdAndEmployeeId, companyId: {}, employeeId: {}", requestId, companyId, employeeId);
        List<CompanyWithDepartmentInfoRespVo> voList = hrEmployeeManagementService.queryOtherCompanyAndDepartmentByCompanyIdAndEmployeeId(companyId, employeeId);
        log.info("requestId {}, hr view, /queryOtherCompanyAndDepartmentByCompanyIdAndEmployeeId, response: {}", requestId, JSONObject.toJSONString(voList));
        return ResultGenerator.genSuccessResult(voList);
    }


    /**
     * 3.1.14 为员工绑定其它可点餐的公司及部门信息
     */
    @PostMapping("/bindCompanyAndDepartmentForEmployee")
    public Result<Void> bindCompanyAndDepartmentForEmployee(@Valid @RequestBody EmployeeBindCompanyReqVo reqVo) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /bindCompanyAndDepartmentForEmployee, req: {}", requestId, JSONObject.toJSONString(reqVo));
        hrEmployeeManagementService.bindCompanyAndDepartmentForEmployee(reqVo);
        log.info("requestId {}, hr view, /bindCompanyAndDepartmentForEmployee, successfully", requestId);
        return ResultGenerator.genSuccessResult();
    }


    /**
     * 3.1.15 删除员工与其它可点餐公司及部门信息的绑定关系
     *
     * @param userOtherCompRelationId 员工可点餐的其它公司记录表中的 ID
     */
    @GetMapping("/deleteUserOtherCompRelationById")
    public Result<Void> deleteUserOtherCompRelationById(@RequestParam(value = "userOtherCompRelationId") String userOtherCompRelationId) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /deleteUserOtherCompRelationById, userOtherCompRelationId: {}", requestId, userOtherCompRelationId);
        hrEmployeeManagementService.deleteUserOtherCompRelationById(userOtherCompRelationId);
        log.info("requestId {}, hr view, /deleteUserOtherCompRelationById, successfully", requestId);
        return ResultGenerator.genSuccessResult();
    }


    /**
     * 3.1.16 更改员工其它可点餐公司中的部门信息
     *
     * @param userOtherCompRelationId 员工可点餐的其它公司记录表中的 ID
     * @param departmentId            部门 ID
     */
    @GetMapping("/updateDepartmentIdByUserOtherCompRelationId")
    public Result<Void> updateDepartmentIdByUserOtherCompRelationId(@RequestParam(value = "userOtherCompRelationId") String userOtherCompRelationId,
                                                                    @RequestParam(value = "departmentId") String departmentId) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /updateDepartmentIdByUserOtherCompRelationId, userOtherCompRelationId: {}, departmentId: {}", requestId, userOtherCompRelationId, departmentId);
        hrEmployeeManagementService.updateDepartmentIdByUserOtherCompRelationId(userOtherCompRelationId, departmentId);
        log.info("requestId {}, hr view, /updateDepartmentIdByUserOtherCompRelationId, successfully", requestId);
        return ResultGenerator.genSuccessResult();
    }


    /**
     * 3.1.17 查询员工可点餐的其它公司及部门信息级联列表
     *
     * @param companyId  公司 ID
     * @param employeeId 员工 ID
     */
    @GetMapping("/queryOtherCanOrderFoodCompanyCascadeList")
    public Result<OtherCanOrderFoodCompanyCascadeRespVo> queryOtherCanOrderFoodCompanyCascadeList(@RequestParam(value = "companyId") String companyId,
                                                                                                  @RequestParam(value = "employeeId") String employeeId) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /queryOtherCanOrderFoodCompanyCascadeList, companyId:{}, employeeId: {}", requestId, companyId, employeeId);
        OtherCanOrderFoodCompanyCascadeRespVo vo = hrEmployeeManagementService.queryOtherCanOrderFoodCompanyCascadeList(companyId, employeeId);
        log.info("requestId {}, hr view, /queryOtherCanOrderFoodCompanyCascadeList, response: {}", requestId, JSONObject.toJSONString(vo));
        return ResultGenerator.genSuccessResult(vo);
    }


    /**
     * 3.1.18 保存员工可点餐的其它公司及部门信息
     */
    @PostMapping("/saveCanOrderFoodCompanyForEmployee")
    public Result<Void> saveCanOrderFoodCompanyForEmployee(@Valid @RequestBody UserOtherCompRelationCreateRespVo reqVo) {
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, hr view, /saveCanOrderFoodCompanyForEmployee, req: {}", requestId, JSONObject.toJSONString(reqVo));
        hrEmployeeManagementService.saveCanOrderFoodCompanyForEmployee(reqVo);
        log.info("requestId {}, hr view, /saveCanOrderFoodCompanyForEmployee, successfully", requestId);
        return ResultGenerator.genSuccessResult();
    }
}
